package com.zyl.pool;

import java.util.concurrent.*;

/**
 * @author zhaoyl
 * @date 2024/5/17 9:06
 * @description 说明
 * public ThreadPoolExecutor(int corePoolSize,//核心线程数[线程池维护线程的最少数量]；线程池创建好(new Thread())以后就准备就绪的线程数量，就等待来接收异步任务去执行
 *                       int maximumPoolSize,//最大核心线程数；控制资源（即使100万个异步任务也按最大线程数量运行）
 *                       long keepAliveTime,//超时了没有调用就释放。存活时间；如果当前正在运行的线程数量大于核心数量；释放空闲线程（最大线程数-核心线程数） 只要线程空闲大于指定keepAliveTime。
 *                       TimeUnit unit, // keepAliveTime的时间单位
 *                       BlockingQueue<Runnable> workQueue, //阻塞队列；如果任务有很多，就会将目前多的任务放在队列里面，只要有线程空闲，就会去队列里面取出新的任务继续执行。
 *                       ThreadFactory threadFactory,//线程的创建工厂。
 *                       RejectedExecutionHandler handler)//拒绝策略，如果队列(workQueue)满了，按照指定的拒绝策略，拒绝执行任务。
 *                       {}
 *工作顺序->
 * 1线程池创建，准备好corePoolSize数量的核心线程，准备接受任务。
 * 2新的任务进来，用core准备好的空闲线程执行。
 *   2.1. 核心线程满了，就将再进来的任务放入阻塞队列中，空闲的核心线程就会自己去阻塞队列获取任务执行。
 *   2.2. 阻塞队列满了，就直接开新线程执行，最大只能开到maximumPoolSize指定的值。
 *   2.3. max都执行好了，新建（最大线程数-核心线程数）的空闲线程会在keepAliveTime指定的时间后自动销毁，最终保持到核心线程数(core)的大小。
 *    2.4. 如果线程数开到了max的数量，还有新任务进来，就会使用handler指定的拒绝策略进行处理。
 * 3所有的线程都是由指定的threadFactory创建的。
 *
 * 四种拒绝策略
 * 1、ThreadPoolExecutor.AbortPolicy()
 * 默认的拒绝策略，如果线程池拒绝了任务，直接报错。当任务数大于线程池最大容量+阻塞队列时，丢弃任务并抛出RejectedExecutionException异常。
 * 2、ThreadPoolExecutor.DiscardPolicy
 * 如果线程池拒绝了任务，直接丢弃。丢弃任务，但是不抛出异常
 * 3、ThreadPoolExecutor.DiscardOldestPolicy()
 * 该策略下，抛弃进入队列最早的那个任务，然后尝试把这次拒绝的任务放入队列。丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
 * 4、ThreadPoolExecutor.CallerRunsPolicy()
 * 线程池让调用者去执行：该策略下，在调用者线程（如main()方法）中直接执行被拒绝任务的run方法，如果当前线程池已经shutdown，则直接抛弃任务。
 */
public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        //创建自定义线程池
        /**
         * 最大线程如何定义
         * 1.cpu密集型：几核就是几，可以保持cpu效率最高
         * 2.IO密集型：要大于 ->判断程序中十分消耗IO的线程
         * */
        System.out.println("当前系统核数："+Runtime.getRuntime().availableProcessors());
        int max = Runtime.getRuntime().availableProcessors();
          max=5;//这里指定下
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                max,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),//默认工厂
                new ThreadPoolExecutor.AbortPolicy()//默认策略：超出抛出异常
                );

        try {
            //最大线程承载数=队列Deque+max=3+5=8
            for (int i=0;i<8;i++){
                //使用线程池创建线程
                threadPool.execute(()->{
                    System.out.println("线程:"+Thread.currentThread().getName()+"->创建OK");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            threadPool.shutdown();//关闭线程池
        }

    }
}
